#include "FormPicRect.h"
#include "tools/cJSON.h"
#include <QDropEvent>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QDesktopWidget>
#include <QTabWidget>

QString strPosNormal = QString("归一化坐标");
QString strPosUnNormal = QString("真实像素点坐标");
QString strObjInfo = QString("单个坐标输入");
QString strArrInfo = QString("批量多个坐标输入");
QString strObject = QString("{\"x\":0.1,\"y\":0.2,\"width\":0.3,\"height\":0.4}");
QString strArray = QString("[{\"x\":0.1,\"y\":0.2,\"width\":0.3,\"height\":0.4}]");

DialogPainter::DialogPainter(QWidget * parent)
        : BaseDialog(parent)
        , m_pTabWidget(nullptr)
        , m_pColorDialog(nullptr)
        , m_pGroupRectParam(nullptr)
        , m_pLineX(nullptr)
        , m_pLineY(nullptr)
        , m_pLineW(nullptr)
        , m_pLineH(nullptr)
        , m_pLineInfoWidth(nullptr)
        , m_pLineInfoHeight(nullptr)
        , m_pLineInfoFormat(nullptr)
        , m_pColorInfo(nullptr)
        , m_pColorShow(nullptr)
        , m_pSpinSize(nullptr)
        , m_pParamInput(nullptr)
        , m_pLineKeyX(nullptr)
        , m_pLineKeyY(nullptr)
        , m_pLineKeyW(nullptr)
        , m_pLineKeyH(nullptr)
        , m_pCheckArray(nullptr)
        , m_pCheckEditKey(nullptr)
        , m_pCheckNormal(nullptr)
{
    setWindowTitle(QString("绘制参数"));
    setFixedSize(650, 500);

    m_pTabWidget = new QTabWidget(this);
    addWidget2BaseLayout(m_pTabWidget);

    m_pColorDialog = new QColorDialog(this);
    connect(m_pColorDialog, SIGNAL(colorSelected(const QColor &)), this, SLOT(slt_ColorSelected(const QColor)));

    m_SelectedColor.setRed(0);
    m_SelectedColor.setGreen(255);
    m_SelectedColor.setBlue(0);

    m_pSpinSize = new QSpinBox(this);
    m_pSpinSize->setMinimumWidth(80);
    m_pSpinSize->setFont(gstEnglishFont);
    m_pSpinSize->setAlignment(Qt::AlignCenter);
    m_pSpinSize->setMaximum(50);
    m_pSpinSize->setMinimum(1);
    m_pSpinSize->setValue(2);

    QWidget* pWidgetParam = new QWidget(this);
    QWidget* pWidgetParse = new QWidget(this);
    m_pTabWidget->addTab(pWidgetParam, QString("基本参数"));
    m_pTabWidget->addTab(pWidgetParse, QString("报文解析"));
    pWidgetParam->setFont(gstFont);
    pWidgetParse->setFont(gstFont);

    // 添加参数直接输入界面
    QVBoxLayout* pLayoutParams = new QVBoxLayout;
    pWidgetParam->setLayout(pLayoutParams);
    QLabel *pLabelInfo = new QLabel(pWidgetParam);          // 基本参数说明

    QGroupBox *pGroupBoxHelpInfo = new QGroupBox(pWidgetParam);
    QHBoxLayout* pLayoutHelpInfo = new QHBoxLayout;
    pGroupBoxHelpInfo->setLayout(pLayoutHelpInfo);
    pLayoutHelpInfo->addWidget(pLabelInfo);
    pGroupBoxHelpInfo->setTitle(QString("使用说明"));
    pLabelInfo->setText(QString("1、支持图片上方框绘制，方框线条颜色和大小可设置；\n2、支持单个或者批量坐标框绘制，坐标框支持归一化和真实像素点；\n3、批量坐标框以JSON形式输入，坐标框关键值可配置。"));
    pLabelInfo->setFont(QFont("楷体", 10));

    QGroupBox *pGroupBoxColorSize = new QGroupBox(pWidgetParam);    // 颜色选择
    QVBoxLayout* pLayoutColorSize = new QVBoxLayout;
    pGroupBoxColorSize->setLayout(pLayoutColorSize);
    QHBoxLayout* pColorShow = new QHBoxLayout;                      // 颜色值选择
    QHBoxLayout* pSpinSize = new QHBoxLayout;                       // 颜色值选择
    pLayoutColorSize->addLayout(pColorShow);
    pLayoutColorSize->addLayout(pSpinSize);
    pGroupBoxColorSize->setTitle(QString("颜色、线条和坐标"));

    QGroupBox *pGroupBoxRectKey = new QGroupBox(pWidgetParam);
    QHBoxLayout* pRectKey = new QHBoxLayout;            // 坐标关键字限定
    pGroupBoxRectKey->setLayout(pRectKey);
    pGroupBoxRectKey->setTitle(QString("坐标关键字"));

    QGroupBox *pGroupBoxImgInfo = new QGroupBox(pWidgetParam);
    QHBoxLayout* pImgInfo = new QHBoxLayout;                // 图片信息展示
    pGroupBoxImgInfo->setLayout(pImgInfo);
    pGroupBoxImgInfo->setTitle(QString("已加载图片信息"));

    m_pGroupRectParam = new QGroupBox(pWidgetParam);
    QHBoxLayout* pParams = new QHBoxLayout;                 // 单个坐标参数输入
    m_pGroupRectParam->setLayout(pParams);
    m_pGroupRectParam->setTitle(QString("单个坐标框(%1)").arg(strPosNormal));

    pLayoutParams->addWidget(pGroupBoxHelpInfo);
    pLayoutParams->addStretch();
    pLayoutParams->addWidget(pGroupBoxColorSize);
    pLayoutParams->addStretch();
    pLayoutParams->addWidget(pGroupBoxImgInfo);
    pLayoutParams->addStretch(); 
    pLayoutParams->addWidget(pGroupBoxRectKey);
    pLayoutParams->addStretch();
    pLayoutParams->addWidget(m_pGroupRectParam);
    pLayoutParams->addStretch();

    // 单个坐标值输入部分
    m_pLineX = new QLineEdit(pWidgetParam);
    m_pLineY = new QLineEdit(pWidgetParam);
    m_pLineW = new QLineEdit(pWidgetParam);
    m_pLineH = new QLineEdit(pWidgetParam);
    QLabel *pLabelX = new QLabel(QString("X: "));
    QLabel *pLabelY = new QLabel(QString("Y: "));
    QLabel *pLabelW = new QLabel(QString("W: "));
    QLabel *pLabelH = new QLabel(QString("H: "));
    pLabelX->setFont(gstEnglishFont);
    pLabelY->setFont(gstEnglishFont);
    pLabelW->setFont(gstEnglishFont);
    pLabelH->setFont(gstEnglishFont);
    m_pLineX->setFont(gstEnglishFont);
    m_pLineY->setFont(gstEnglishFont);
    m_pLineW->setFont(gstEnglishFont);
    m_pLineH->setFont(gstEnglishFont);
    m_pLineX->setAlignment(Qt::AlignCenter);
    m_pLineY->setAlignment(Qt::AlignCenter);
    m_pLineW->setAlignment(Qt::AlignCenter);
    m_pLineH->setAlignment(Qt::AlignCenter);
    pParams->addWidget(pLabelX);
    pParams->addWidget(m_pLineX);
    pParams->addWidget(pLabelY);
    pParams->addWidget(m_pLineY);
    pParams->addWidget(pLabelW);
    pParams->addWidget(m_pLineW);
    pParams->addWidget(pLabelH);
    pParams->addWidget(m_pLineH);

    // 颜色、线条和归一化配置
    QPushButton *pBtnColour = NewPTBWithIcon(QString("颜色选择"), QString("打开颜色对话框(按下Enter键快速打开)"), QIcon(QString(":/operationIcons/resource/operationIcons/draw_krita.ico")), this);
    connect(pBtnColour, SIGNAL(clicked()), this, SLOT(stl_OpenColorDialog()));
    //m_pColorInfo = new QLabel(QString("颜色值：R[%1] - G[%2] - B[%3]").arg(QString::number(m_SelectedColor.red()), QString::number(m_SelectedColor.green()), QString::number(m_SelectedColor.blue())));
    m_pColorInfo = new QLineEdit(pGroupBoxColorSize);
    m_pColorInfo->setText(QString("R[%1] - G[%2] - B[%3]").arg(QString::number(m_SelectedColor.red()), QString::number(m_SelectedColor.green()), QString::number(m_SelectedColor.blue())));
    m_pColorInfo->setAlignment(Qt::AlignCenter);
    m_pColorInfo->setFont(gstEnglishFont);
    m_pColorInfo->setEnabled(false);
    m_pColorInfo->setMinimumWidth(220);
    
    m_pColorShow = new QLabel;
    m_pColorShow->setStyleSheet(QString("QLabel{background-color:rgb(%1, %2, %3);}").arg(QString::number(m_SelectedColor.red()), QString::number(m_SelectedColor.green()), QString::number(m_SelectedColor.blue())));
    m_pColorShow->setMinimumWidth(200);

    pColorShow->addWidget(pBtnColour);
    pColorShow->addStretch();
    pColorShow->addWidget(m_pColorInfo);
    pColorShow->addStretch();
    pColorShow->addWidget(m_pColorShow);

    QLabel *pLabelSpinSize = new QLabel(QString("线条大小："));
    m_pCheckNormal = new MyCheckBox();
    m_pCheckNormal->setText(QString("坐标归一化"));
    m_pCheckNormal->setFont(gstFont);
    m_pCheckNormal->setFlat(true);
    m_pCheckNormal->setToolTip(QString("选中该项，则坐标以归一化方式获取，数值范围在[0.0, 1.0]，否则为真实像素点位置"));
    connect(m_pCheckNormal, SIGNAL(SendClicked(bool)), this, SLOT(slt_NormalStateChanged(bool)));
    m_pCheckNormal->setStatus(true);    // 默认使用归一化坐标

    m_pCheckEditKey = new MyCheckBox();
    m_pCheckEditKey->setText(QString("修改关键字"));
    m_pCheckEditKey->setFont(gstFont);
    m_pCheckEditKey->setFlat(true);
    m_pCheckEditKey->setToolTip(QString("选中该项，则支持坐标关键字修改和报文数组/对象修改，否则以默认关键字解析"));
    connect(m_pCheckEditKey, SIGNAL(SendClicked(bool)), this, SLOT(slt_EditKeyStateChanged(bool)));

    m_pCheckArray = new MyCheckBox();
    m_pCheckArray->setText(QString("坐标数组"));
    m_pCheckArray->setFont(gstFont);
    m_pCheckArray->setFlat(true);
    m_pCheckArray->setToolTip(QString("选中该项，则输入报文将以数组方式解析，否则以单个对象方式解析"));
    connect(m_pCheckArray, SIGNAL(SendClicked(bool)), this, SLOT(slt_ArrayStateChanged(bool)));

    pSpinSize->addWidget(pLabelSpinSize);
    pSpinSize->addWidget(m_pSpinSize);
    pSpinSize->addStretch();
    pSpinSize->addWidget(m_pCheckNormal);
    pSpinSize->addStretch();
    pSpinSize->addWidget(m_pCheckEditKey);
    pSpinSize->addStretch();
    pSpinSize->addWidget(m_pCheckArray);
    pSpinSize->addStretch();

    // 添加关键字输入部分
    m_pLineKeyX = new QLineEdit(pWidgetParam);
    m_pLineKeyY = new QLineEdit(pWidgetParam);
    m_pLineKeyW = new QLineEdit(pWidgetParam);
    m_pLineKeyH = new QLineEdit(pWidgetParam);
    QLabel *pLabelKeyX = new QLabel(QString("X: "));
    QLabel *pLabelKeyY = new QLabel(QString("Y: "));
    QLabel *pLabelKeyW = new QLabel(QString("W: "));
    QLabel *pLabelKeyH = new QLabel(QString("H: "));
    pLabelKeyX->setFont(gstEnglishFont);
    pLabelKeyY->setFont(gstEnglishFont);
    pLabelKeyW->setFont(gstEnglishFont);
    pLabelKeyH->setFont(gstEnglishFont);
    m_pLineKeyX->setFont(gstEnglishFont);
    m_pLineKeyY->setFont(gstEnglishFont);
    m_pLineKeyW->setFont(gstEnglishFont);
    m_pLineKeyH->setFont(gstEnglishFont);
    m_pLineKeyX->setAlignment(Qt::AlignCenter);
    m_pLineKeyY->setAlignment(Qt::AlignCenter);
    m_pLineKeyW->setAlignment(Qt::AlignCenter);
    m_pLineKeyH->setAlignment(Qt::AlignCenter);
    m_pLineKeyX->setText(QString("x"));
    m_pLineKeyY->setText(QString("y"));
    m_pLineKeyW->setText(QString("width"));
    m_pLineKeyH->setText(QString("height"));
    m_pLineKeyX->setEnabled(false);
    m_pLineKeyY->setEnabled(false);
    m_pLineKeyW->setEnabled(false);
    m_pLineKeyH->setEnabled(false);

    pRectKey->addWidget(pLabelKeyX);
    pRectKey->addWidget(m_pLineKeyX);
    pRectKey->addWidget(pLabelKeyY);
    pRectKey->addWidget(m_pLineKeyY);
    pRectKey->addWidget(pLabelKeyW);
    pRectKey->addWidget(m_pLineKeyW);
    pRectKey->addWidget(pLabelKeyH);
    pRectKey->addWidget(m_pLineKeyH);

    // 图片详细信息展示
    QLabel *pImgWidth = new QLabel(QString("宽度"));
    QLabel *pImgHeight = new QLabel(QString("高度"));
    QLabel *pImgFormat = new QLabel(QString("格式"));
    m_pLineInfoWidth = new QLineEdit(pWidgetParam);
    m_pLineInfoHeight = new QLineEdit(pWidgetParam);
    m_pLineInfoFormat = new QLineEdit(pWidgetParam);
    m_pLineInfoWidth->setAlignment(Qt::AlignCenter);
    m_pLineInfoHeight->setAlignment(Qt::AlignCenter);
    m_pLineInfoFormat->setAlignment(Qt::AlignCenter);
    m_pLineInfoWidth->setEnabled(false);
    m_pLineInfoHeight->setEnabled(false);
    m_pLineInfoFormat->setEnabled(false);
    pImgInfo->addWidget(pImgWidth);
    pImgInfo->addWidget(m_pLineInfoWidth);
    pImgInfo->addWidget(pImgHeight);
    pImgInfo->addWidget(m_pLineInfoHeight);
    pImgInfo->addWidget(pImgFormat);
    pImgInfo->addWidget(m_pLineInfoFormat);

    // 添加参数解析窗口
    QVBoxLayout *pLayoutParse = new QVBoxLayout;
    pWidgetParse->setLayout(pLayoutParse);
    m_pParamInput = new QTextEdit(pWidgetParse);
    pLayoutParse->addWidget(m_pParamInput);
    m_pParamInput->setPlaceholderText(QStringLiteral("输入坐标系JSON报文，报文规则和坐标关键字可在【基本参数】页配置\n当前规则：支持%1，坐标为%2\n用例：\n%3").arg(strObjInfo, strPosNormal, strObject));

    // 底部工具栏按钮
    QPushButton *pBtnClear = NewPTBWithIcon(QString("清空"), QString("清空当前标签页参数"), QIcon(QString(":/operationIcons/resource/operationIcons/clear_format.ico")), this);
    connect(pBtnClear, SIGNAL(clicked()), this, SLOT(slt_Clear()));
    QPushButton *pBtnDraw = NewPTBWithIcon(QString("绘制"), QString("将输入坐标参数在图片上绘制"), QIcon(QString(":/operationIcons/resource/operationIcons/draw_pencil.ico")), this);
    connect(pBtnDraw, SIGNAL(clicked()), this, SLOT(slt_DrawRect()));
    pBtnClear->setFont(gstFont);
    pBtnDraw->setFont(gstFont);

    addWidget2FuncLayout(pBtnClear);
    addFuncStretch();
    addWidget2FuncLayout(pBtnDraw);
    addFuncLayout();
}

// 获取已选择的颜色和大小
void DialogPainter::GetColorSize(QColor &color, uint &iSize)
{
    color = m_SelectedColor;
    iSize = m_pSpinSize->value();
}

// 更新当前展示图片的详细信息
void DialogPainter::SetImageInfo(const IMG_INFO_S& stInfo)
{
    m_pLineInfoWidth->setText(QString::number(stInfo.iWidth));
    m_pLineInfoHeight->setText(QString::number(stInfo.iHeight));
    m_pLineInfoFormat->setText(stInfo.strFormat);
}

// 获取颜色值
void DialogPainter::stl_OpenColorDialog()
{
    if(nullptr != m_pColorDialog)
    {
        m_pColorDialog->exec();
    }
}

// 颜色选择更新
void DialogPainter::slt_ColorSelected(const QColor &color)
{
    m_SelectedColor = color;
    m_pColorInfo->setText(QString("R[%1] - G[%2] - B[%3]").arg(QString::number(m_SelectedColor.red()), QString::number(m_SelectedColor.green()), QString::number(m_SelectedColor.blue())));
    m_pColorShow->setStyleSheet(QString("QLabel{background-color:rgb(%1, %2, %3);}").arg(QString::number(m_SelectedColor.red()), QString::number(m_SelectedColor.green()), QString::number(m_SelectedColor.blue())));
}

// 坐标类型按钮状态修改
void DialogPainter::slt_NormalStateChanged(bool bStatus)
{
    QString str0 = strObjInfo;
    QString str1 = strPosUnNormal;
    QString str2 = strObject;
    if(true == bStatus)
    {
        m_pGroupRectParam->setTitle(QString("单个坐标框(归一化坐标)"));
        str1 = strPosNormal;
    }
    else
    {
        m_pGroupRectParam->setTitle(QString("单个坐标框(真实像素点坐标)"));
    }

    if(true == m_pCheckArray->getStatus())
    {
        str0 = strArrInfo;
        str2 = strArray;
    }

    // 更新规则输入框中的帮助信息
    m_pParamInput->setPlaceholderText(QStringLiteral("输入坐标系JSON报文，报文规则和坐标关键字可在【基本参数】页配置\n当前规则：支持%1，坐标为%2\n用例：\n%3").arg(str0, str1, str2));
}

// 修改关键字按钮状态修改
void DialogPainter::slt_EditKeyStateChanged(bool bStatus)
{
    m_pLineKeyX->setEnabled(bStatus);
    m_pLineKeyY->setEnabled(bStatus);
    m_pLineKeyW->setEnabled(bStatus);
    m_pLineKeyH->setEnabled(bStatus);
}

// 修改数组和对象切换按钮状态
void DialogPainter::slt_ArrayStateChanged(bool bStatus)
{
    QString str0 = strObjInfo;
    QString str1 = strPosUnNormal;
    QString str2 = strObject;
    if(m_pCheckNormal->getStatus())
    {
        str1 = strPosNormal;
    }

    if(true == bStatus)
    {
        str0 = strArrInfo;
        str2 = strArray;
    }

    // 更新规则输入框中的帮助信息
    m_pParamInput->setPlaceholderText(QStringLiteral("输入坐标系JSON报文，报文规则和坐标关键字可在【基本参数】页配置\n当前规则：支持%1，坐标为%2\n用例：\n%3").arg(str0, str1, str2));
}

// 清空参数
void DialogPainter::slt_Clear()
{
    int idx = m_pTabWidget->currentIndex();
    switch (idx) {
    case 0:
        m_pLineX->clear();
        m_pLineY->clear();
        m_pLineW->clear();
        m_pLineH->clear();

        break;
    case 1:
        m_pParamInput->clear();
        break;
    case 2:
        break;
    default:
        break;
    }
}

// 发送绘制信息
void DialogPainter::slt_DrawRect()
{
    int idx = m_pTabWidget->currentIndex();
    QVector<IMG_RECT_FLOAT> vecParamFloat;
    QVector<IMG_RECT_INT>   vecParamInt;
    switch (idx) {
    case 0:
    {
        // 校验当前界面输出坐标结果
        QString strX = m_pLineX->text();
        QString strY = m_pLineY->text();
        QString strW = m_pLineW->text();
        QString strH = m_pLineH->text();
        if(strX.isEmpty() || strY.isEmpty() || strW.isEmpty() || strH.isEmpty())
        {
            myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("部分参数为空，请输入有效坐标值，范围[0.0, 1.0]"));
            break;
        }

        if(false == checkValidNumber(strX) || false == checkValidNumber(strY) || false == checkValidNumber(strW) || false == checkValidNumber(strH))
        {
            myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("参数校验失败！坐标值非有效数字"));
            break;
        }

        if(true == m_pCheckNormal->getStatus())
        {
            // 使用归一化坐标，浮点数
            IMG_RECT_FLOAT stRect;
            stRect.fX = strX.toFloat();
            stRect.fY = strY.toFloat();
            stRect.fWidth = strW.toFloat();
            stRect.fHeight = strH.toFloat();

            if(false == stRect.check())
            {
                myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("坐标参数范围必须为[0.0, 1.0]之间，请检查有效性"));
                break;
            }
            else
            {
                vecParamFloat.push_back(stRect);
            }
        }
        else
        {
            // 使用真实坐标
            IMG_RECT_INT stRect;
            stRect.iX = strX.toInt();
            stRect.iY = strY.toInt();
            stRect.iWidth = strW.toInt();
            stRect.iHeight = strH.toInt();

            vecParamInt.push_back(stRect);
        }

        break;
    }
    case 1:
    {
        // 报文解析并按规则输出坐标结果
        parseParams(vecParamFloat, vecParamInt);
        break;
    }
    default:
        break;
    }

    if(!vecParamFloat.isEmpty() || !vecParamInt.isEmpty())
    {
        emit sendParams(vecParamFloat, vecParamInt); // 坐标数组不为空，发送数据
    }
}

// 解析输入报文
bool DialogPainter::parseParams(QVector<IMG_RECT_FLOAT>& vecParamFloat, QVector<IMG_RECT_INT>& vecParamInt)
{
    vecParamFloat.clear();
    vecParamInt.clear();

    bool bStatus = false;
    cJSON *pRoot = nullptr;
    uint iErrCnt = 0;
    uint iSize = 0;
    do
    {
        // 获取指定关键字
        QString strKeyX = m_pLineKeyX->text();
        QString strKeyY = m_pLineKeyY->text();
        QString strKeyW = m_pLineKeyW->text();
        QString strKeyH = m_pLineKeyH->text();
        if(strKeyX.isEmpty() || strKeyY.isEmpty() || strKeyW.isEmpty() || strKeyH.isEmpty())
        {
            myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("获取坐标框关键字失败"));
            break;
        }

        // 获取解析类型：对象或数组
        bool bArray = m_pCheckArray->getStatus();

        QString strRule = m_pParamInput->document()->toPlainText();
        if(strRule.isEmpty())
        {
            myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("获取坐标框报文失败，请检查是否已输入报文"));
            break;
        }

        pRoot = cJSON_Parse(strRule.toStdString().c_str());
        if(nullptr == pRoot)
        {
            myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("解析坐标框报文失败，请检查报文有效性"));
            break;
        }
        if(true == bArray)
        {
            iSize = cJSON_GetArraySize(pRoot);
            for (uint idx = 0; idx < iSize; idx++)
            {
                cJSON* pObj = cJSON_GetArrayItem(pRoot, idx);
                if(nullptr == pObj)
                {
                    myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("读取坐标框数组存在异常，异常位置[%1:%2]").arg(QString::number(iSize), QString::number(idx)));
                    break;
                }

                cJSON* pX = cJSON_GetObjectItem(pObj, strKeyX.toStdString().c_str());
                cJSON* pY = cJSON_GetObjectItem(pObj, strKeyY.toStdString().c_str());
                cJSON* pW = cJSON_GetObjectItem(pObj, strKeyW.toStdString().c_str());
                cJSON* pH = cJSON_GetObjectItem(pObj, strKeyH.toStdString().c_str());
                if(nullptr == pX || nullptr == pY || nullptr == pW || nullptr == pH)
                {
                    myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("读取坐标框关键字存在异常，异常位置[%1:%2]").arg(QString::number(iSize), QString::number(idx)));
                    break;
                }

                if(true == m_pCheckNormal->getStatus())
                {
                    // 归一化方式解析，读取浮点数
                    IMG_RECT_FLOAT stRect;
                    stRect.fX = pX->valuedouble;
                    stRect.fY = pY->valuedouble;
                    stRect.fWidth = pW->valuedouble;
                    stRect.fHeight = pH->valuedouble;
                    if(true == stRect.check())
                    {
                        vecParamFloat.push_back(stRect);
                    }
                    else
                    {
                        iErrCnt++;
                    }
                }
                else
                {
                    // 真实像素点坐标解析，读取整型值
                    IMG_RECT_INT stRect;
                    stRect.iX = pX->valueint;
                    stRect.iY = pY->valueint;
                    stRect.iWidth = pW->valueint;
                    stRect.iHeight = pH->valueint;
                    vecParamInt.push_back(stRect);
                }
            }
        }
        else
        {
            cJSON* pX = cJSON_GetObjectItem(pRoot, strKeyX.toStdString().c_str());
            cJSON* pY = cJSON_GetObjectItem(pRoot, strKeyY.toStdString().c_str());
            cJSON* pW = cJSON_GetObjectItem(pRoot, strKeyW.toStdString().c_str());
            cJSON* pH = cJSON_GetObjectItem(pRoot, strKeyH.toStdString().c_str());
            if(nullptr == pX || nullptr == pY || nullptr == pW || nullptr == pH)
            {
                myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_ERROR, QString("单个对象解析，读取坐标框关键字存在异常"));
                break;
            }

            if(true == m_pCheckNormal->getStatus())
            {
                // 归一化方式解析，读取浮点数
                IMG_RECT_FLOAT stRect;
                stRect.fX = pX->valuedouble;
                stRect.fY = pY->valuedouble;
                stRect.fWidth = pW->valuedouble;
                stRect.fHeight = pH->valuedouble;
                if(true == stRect.check())
                {
                    vecParamFloat.push_back(stRect);
                }
                else
                {
                    iErrCnt++;
                }
            }
            else
            {
                // 真实像素点坐标解析，读取整型值
                IMG_RECT_INT stRect;
                stRect.iX = pX->valueint;
                stRect.iY = pY->valueint;
                stRect.iWidth = pW->valueint;
                stRect.iHeight = pH->valueint;
                vecParamInt.push_back(stRect);
            }
        }

        bStatus = true;
    }while(0);

    if(nullptr != pRoot)
    {
        cJSON_Delete(pRoot);
        pRoot = nullptr;
    }

    uint iReadSize = ((true == vecParamFloat.isEmpty()) ? vecParamInt.size() : vecParamFloat.size());
    myMessageBoxShowOne(FORM_PICRECT, MSG_SHOW_INFO, QString("从报文中读取有效坐标框个数[%1],异常坐标框个数[%2]").arg(QString::number(iReadSize), QString::number(iErrCnt)));

    return bStatus;
}

// 子标签页窗口
FormPicRect::FormPicRect(QWidget * parent)
        : BaseFormWidget(parent)
        , m_pPainter(nullptr)
        , m_fileDialog(nullptr)
        , m_pImgLabelShow(nullptr)
{
    m_stImageInfo.clear();
    m_vecImages.clear();
    m_iImageShowIndex = IMAGE_INDEX_INVALID;

    m_pPainter = new DialogPainter(this);
    connect(m_pPainter, SIGNAL(sendParams(QVector<IMG_RECT_FLOAT>&, QVector<IMG_RECT_INT>&)), this, SLOT(slt_PaintWithParams(QVector<IMG_RECT_FLOAT>&, QVector<IMG_RECT_INT>&)));
    m_pImgLabelShow = new QLabel(this);
    m_pImgLabelShow->setAlignment(Qt::AlignCenter);
    m_pImgLabelShow->setText(QString("支持JPG和PNG图片直接拖拽到本区域读取，其他格式图片请通过【打开】方式获取"));
    m_pImgLabelShow->setFont(gstFont);
    //m_pImgLabelShow->setStyleSheet("QLabel{background-color:rgb(198, 252, 201);}");
    addWidget2BaseLayout(m_pImgLabelShow, Qt::AlignBottom);

    // 支持文件拖拽到本区域
    setAcceptDrops(true);

    // 创建功能按钮
    newFuncPtb();

    // 添加顶部工具栏
    newBaseClose();

    // 所有按钮统一设置风格
    setBaseFont(gstFont);

    m_fileDialog = new QFileDialog(this); 
    m_fileDialog->setAcceptMode(QFileDialog::AcceptSave);
    m_fileDialog->setWindowTitle("另存为...");
    m_fileDialog->setLabelText(QFileDialog::Accept, "保存");
    m_fileDialog->setLabelText(QFileDialog::Reject, "取消");
}

// 设置全局字体和大小
void FormPicRect::setFont(const QFont &stFont)
{
    setBaseFont(stFont);
}

// 创建功能按钮
void FormPicRect::newFuncPtb()
{
    QPushButton *pBtnOpenFile = NewPTBWithIcon(QString("打开"), QString("打开图片文件"), QIcon(QString(":/operationIcons/resource/operationIcons/file_open.ico")), this);
    QPushButton *pBtnSave = NewPTBWithIcon(QString("保存"), QString("保存已绘制图片到本地"), QIcon(QString(":/operationIcons/resource/operationIcons/file_save.ico")), this);
    QPushButton *pBtnBack = NewPTBWithIcon(QString("后退"), QString("后退到上一张图"), QIcon(QString(":/operationIcons/resource/operationIcons/back.ico")), this);
    QPushButton *pBtnNext = NewPTBWithIcon(QString("前进"), QString("前进到下一张图"), QIcon(QString(":/operationIcons/resource/operationIcons/next.ico")), this);
    QPushButton *pBtnPaintParams = NewPTBWithIcon(QString("绘制面板"), QString("绘制参数输入"), QIcon(QString(":/operationIcons/resource/operationIcons/paint.ico")), this);

    connect(pBtnOpenFile, SIGNAL(clicked()), this, SLOT(slt_OpenFile()));
    connect(pBtnSave, SIGNAL(clicked()), this, SLOT(slt_Save()));
    connect(pBtnBack, SIGNAL(clicked()), this, SLOT(slt_Back()));
    connect(pBtnNext, SIGNAL(clicked()), this, SLOT(slt_Next()));
    connect(pBtnPaintParams, SIGNAL(clicked()), this, SLOT(slt_ShowPaintParams()));

    addBaseToolFunc(pBtnOpenFile);
    addBaseToolFunc(pBtnSave);
    addBaseToolFunc(pBtnBack);
    addBaseToolFunc(pBtnNext);
    addBaseToolFunc(pBtnPaintParams);

    // 后续按钮靠右排列
    addBaseFuncStretch();
}

// 打开文件
void FormPicRect::slt_OpenFile()
{
    QString aFileName = GetFileFromFileDialog(this, QString("所有文件(*.*)"));
    if(aFileName.isEmpty())
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("未选择有效文件!"));
        return;
    }

    QImage pImgTemp;
    if(true == getImgFromPath(pImgTemp, aFileName))
    {
        if(!pImgTemp.isNull())
        {
            // 更新图片信息
            m_stImageInfo.clear();
            m_stImageInfo.iHeight = pImgTemp.height();
            m_stImageInfo.iWidth = pImgTemp.width();
            m_stImageInfo.strFormat = getFormatFromFile(aFileName);
            
            // 清空已有
            m_vecImages.clear();

            // 更新图片展示
            showImage(pImgTemp);
        }
    }
    else
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("文件[%1]读取失败!").arg(aFileName));
    }
}

// 保存文件
void FormPicRect::slt_Save()
{
    // 没有图片，返回
    if(IMAGE_INDEX_INVALID == m_iImageShowIndex || m_iImageShowIndex > (int)m_vecImages.size())
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("未加载有效图片"));
        return;
    }

    QImage &pImgTemp = m_vecImages[m_iImageShowIndex];

    // 未操作图片，返回，不做保存
    if(pImgTemp.isNull() || m_stImageInfo.strFormat.isEmpty())
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("图片数据为空或识别读取图片格式异常[%1]，可能未执行过图片").arg(m_stImageInfo.strFormat));
        return;
    }

    // 先获取已配置路径，配置路径不存在，则选择获取当前程序运行路径
    QString curPath = AnaConfig::Instance().getSavePathWithAsk(this);
    if(curPath.isEmpty())
    {
        curPath = QCoreApplication::applicationDirPath();
    }

    m_fileDialog->setDirectory(curPath); 
    if(m_fileDialog->exec() != QDialog::Accepted)
    {
        return;
    }

    QString strPath = m_fileDialog->selectedFiles().at(0);

    uint iImgWidth = pImgTemp.width();
    uint iImgHeight = pImgTemp.height();
    QString strFileName = strPath + QString(".") + m_stImageInfo.strFormat;
    pImgTemp.save(strFileName, m_stImageInfo.strFormat.toStdString().c_str(), 100);
    myMessageBoxShowOne(m_eProcType, MSG_SHOW_INFO, QString("写入文件 %1 成功！\n图片大小为 %2 x %3").arg(strFileName, QString::number(iImgWidth), QString::number(iImgHeight)));
}

// 返回上一张图（如有）
void FormPicRect::slt_Back()
{
    if(IMAGE_INDEX_INVALID == m_iImageShowIndex)
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("未加载有效图片"));
        return;
    }

    int iIndex = m_iImageShowIndex - 1;
    if(iIndex >= 0 && iIndex < (int)m_vecImages.size())
    {
        showImage(m_vecImages[iIndex], false);
        m_iImageShowIndex--;
    }
    else
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("已经是最前一张图"));
    }
}

// 跳到下一张图（如有）
void FormPicRect::slt_Next()
{
    if(IMAGE_INDEX_INVALID == m_iImageShowIndex)
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("未加载有效图片"));
        return;
    }

    int iIndex = m_iImageShowIndex + 1;
    if(iIndex >= 0 && iIndex < (int)m_vecImages.size())
    {
        showImage(m_vecImages[iIndex], false);
        m_iImageShowIndex++;
    }
    else
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("已经是最后一张图"));
    }
}

// 绘制参数输入
void FormPicRect::slt_ShowPaintParams()
{
    if(nullptr != m_pPainter)
    {
        m_pPainter->SetImageInfo(m_stImageInfo);
        m_pPainter->show();
    }
}

// 接收坐标参数并在图片上绘制
void FormPicRect::slt_PaintWithParams(QVector<IMG_RECT_FLOAT>& vecParamFloat, QVector<IMG_RECT_INT>& vecParamInt)
{
    if(vecParamFloat.isEmpty() && vecParamInt.isEmpty())
    {
        return;
    }

    // 当前图片列表不为空
    if(IMAGE_INDEX_INVALID == m_iImageShowIndex)
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("未加载图片，无法执行画框任务"));
        return;
    }

    QImage pImgTemp = m_vecImages[m_iImageShowIndex];
    if(pImgTemp.isNull())
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("所加载图片异常，无法执行画框任务"));
        return;
    }

    QColor pColor;
    uint iSize;
    m_pPainter->GetColorSize(pColor, iSize);
    if(false == pColor.isValid())
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("输入颜色值参数异常，请检查"));
        return;
    }

    if(0 == iSize)
    {
        myMessageBoxShowOne(m_eProcType, MSG_SHOW_ERROR, QString("输入线条粗细值为0，请检查"));
        return;
    }

    //qDebug() << "slt_PaintWithParams: " << vecParamFloat.size() << pColor << iSize;
    QRgb mRgb = qRgb(pColor.red(), pColor.green(), pColor.blue());
    // 执行多个坐标绘制，之后显示更新
    for(auto it : vecParamFloat)
    {
        picDrawRectNormalization(pImgTemp, it, mRgb, iSize);
    }

    for(auto it : vecParamInt)
    {
        picDrawRectLocation(pImgTemp, it, mRgb, iSize);
    }
    
    showImage(pImgTemp);
}

// 刷新展示图片
void FormPicRect::showImage(QImage pImage, bool bAdd)
{
    if(!pImage.isNull())
    {
        if(m_pImgLabelShow->width() >= pImage.width() && m_pImgLabelShow->height() >= pImage.height())
        {
            // 已有显示框大于图片原始大小，直接显示数据
            m_pImgLabelShow->setPixmap(QPixmap::fromImage(pImage));
        }
        else
        {
            // 重新调整图片规格
            QSize pSize = m_pImgLabelShow->size();
            pSize.setWidth(pSize.width() - 1);
            pSize.setHeight(pSize.height() - 1);
            QImage pImg = pImage.scaled(pSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
            m_pImgLabelShow->setPixmap(QPixmap::fromImage(pImg));
        }

        if(true == bAdd)
        {
            // 未添加图片或当前图片为已有图片的最后一张，则直接添加到最后，否则需删除当前图片之后的所有图片
            if(!( IMAGE_INDEX_INVALID == m_iImageShowIndex || m_iImageShowIndex == (int)(m_vecImages.size() - 1)))
            {
                m_vecImages.erase(m_vecImages.begin() + m_iImageShowIndex + 1, m_vecImages.end());
            }

            m_vecImages.push_back(pImage);
            m_iImageShowIndex = m_vecImages.size() - 1;
        }
    }
}

// 限制拖拽目标类型
void FormPicRect::dragEnterEvent(QDragEnterEvent *event)
{
    if(!event->mimeData()->urls()[0].fileName().right(3).compare("jpg") ||
       !event->mimeData()->urls()[0].fileName().right(3).compare("png") ||
       !event->mimeData()->urls()[0].fileName().right(3).compare("gif") )
    {
        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}

// 接收图片拖拽输入后打开
void FormPicRect::dropEvent(QDropEvent *event)
{
    QString strPath = event->mimeData()->urls()[0].toLocalFile();
    QImage pImgTemp;
    if(true == getImgFromPath(pImgTemp, strPath))
    {
        if(!pImgTemp.isNull())
        {
            // 更新图片信息
            m_stImageInfo.clear();
            m_stImageInfo.iHeight = pImgTemp.height();
            m_stImageInfo.iWidth = pImgTemp.width();
            m_stImageInfo.strFormat = getFormatFromFile(strPath);
            
            // 清空已有数据
            m_vecImages.clear();

            // 更新图片展示
            showImage(pImgTemp);
        }
    }
}

// 变更界面显示比例
void FormPicRect::resizeEvent(QResizeEvent *event)
{
    if(nullptr == event)
    {
        return;
    }

   // showImage();
}
